﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Kugar.Core.ExtMethod;
using Kugar.UI.RazorUI.RazorEngine;

namespace Kugar.UI.RazorUI.RazorEngine
{
    public abstract class RazorViewBase
    {
        private StringBuilder _sb=new StringBuilder(100);
        private TextWriter _writer=null;
        private Lazy<Dictionary<string,Func<Task>>> _cacheSections=new Lazy<Dictionary<string, Func<Task>>>();
        protected object _model = null;


        protected RazorViewBase()
        {
            _writer = new StringWriter(_sb);

            Writer = _writer;
        }
        
        public async virtual Task ExecuteAsync()
        {

        }

        public Dictionary<string, object> ViewData => ViewContext.ViewData;

        public dynamic ViewBag => ViewContext.ViewBag;

        public virtual object Model
        {
            get => _model;
            internal set { _model = value; }
        }

        public string Layout { set; get; }

        public ViewContext ViewContext { get; internal set; }

        public void WriteLiteral(string str)
        {
            Writer.Write(str);
        }

        public void Write(string str)
        {
            Writer.Write(WebUtility.HtmlEncode(str));
        }

        public void Write(HtmlString str)
        {
            str.WriteTo(Writer);
        }

        protected HtmlHelper Html { get; set; }

        protected virtual void DefineSection(string name, Func<Task> act)
        {
            _cacheSections.Value.Add(name, act);
        }


        public HtmlString RenderSection(string sectionName, bool isRequired=false)
        {
            var sb=new StringBuilder();

            var orginalWriter = ChildView.Writer;

            using (var writer=new StringWriter(sb))
            {
                var sectionInvoker = ChildView?.GetSection(sectionName);

                if (isRequired && sectionInvoker == null)
                {
                    throw new NotImplementedException($"Section {sectionName} 未实现");
                }

                ChildView.Writer = writer;

                sectionInvoker?.Invoke().Wait();

                ChildView.Writer = orginalWriter;

                return new HtmlString(sb.ToString());
            }

            
        }

        protected HtmlString RenderBody()
        {
            return new HtmlString(ChildView.Value.ToStringEx());
        }



        internal StringBuilder Value => _sb;

        internal RazorViewBase ChildView { get; set; }

        internal TextWriter Writer
        {
            get;
            set;
        }

        internal Func<Task> GetSection(string name)
        {
            if (_cacheSections.IsValueCreated && _cacheSections.Value.TryGetValue(name, out var sectionInvoker))
            {
                return sectionInvoker;
            }
            else
            {
                return default;
            }
        }

        public void Close()
        {
            _writer.Close();
        }


        ///// <summary>
        ///// 不要调用这个,用于忽悠IDE的
        ///// </summary>
        ///// <param name="name"></param>
        ///// <param name="act"></param>
        //[Browsable(false), Obsolete]
        //protected virtual void DefineSection(string name, Func<Task> act)
        //{

        //}

        /// <summary>
        /// 不要调用这个,用于忽悠IDE的
        /// </summary>
        /// <param name="name"></param>
        /// <param name="act"></param>
        [Browsable(false), Obsolete()]
        public HttpContextFake Context { set; get; }





        /// <summary>
        /// 不要调用这个,用于忽悠IDE的
        /// </summary>
        /// <param name="name"></param>
        /// <param name="act"></param>
        [Browsable(false), Obsolete()]
        protected virtual void DefineSection(string name, Action act)
        {
           
        }

        /// <summary>
        /// 不要调用这个,用于忽悠IDE的
        /// </summary>
        /// <param name="name"></param>
        /// <param name="act"></param>
        [Browsable(false), Obsolete()]
        public virtual void Execute()
        {

        }
    }

    public abstract class RazorViewBase<TModel>: RazorViewBase
    {
        public new TModel Model
        {
            get => (TModel)_model;
            internal set { _model = value; }
        }
    }


    public class Model
    {
        public string A1 { set; get; }
        
    }

    [Browsable(false),Obsolete]
    public class HttpContextFake
    {
        public System.Web.HttpApplication ApplicationInstance { get; }
    }



    public class HtmlString
    {
        private string _value = "";

        public static HtmlString NewLine { get; }=new HtmlString(Environment.NewLine);

        public static HtmlString Empty { get; }=new HtmlString(string.Empty);

        public HtmlString(string value)
        {
            _value = value;
        }

        public void WriteTo(TextWriter stream)
        {
            stream.Write(_value);
        }
    }


    public class HtmlHelper
    {
        private RazorViewBase _currentView = null;

        public HtmlHelper(RazorViewBase view)
        {
            _currentView = view;
        }
        
        public void Raw(string html)
        {
            _currentView.WriteLiteral(html);
        }
    }
    

}

namespace System.Web.WebPages.Html
{
    public class Html
    {
        public object Html1 { set; get; }
    }
    

}

namespace System.Web.WebPages
{
    public abstract  class WebPage: RazorViewBase
    {
    }

    public abstract class WebPage<TModel> : RazorViewBase<TModel>
    {
    }
}

namespace System.Web.Mvc
{
    public abstract class WebViewPage : RazorViewBase
    {
    }

    public abstract class WebViewPage<TModel> : RazorViewBase<TModel>
    {
    }
}

namespace System.Web.Helpers
{
    public class Html
    {
        public object Html1 { set; get; }
    }
}

